package app.server.project.main.service.service.upay.tron;

import app.server.project.core.constants.Def;
import app.server.project.main.service.bo.event.upay.tron.ActiveEvent;
import app.server.project.main.service.bo.event.upay.tron.ChkActiveEvent;
import app.server.project.main.service.db.dao.cfg.GlobalCfgDao;
import app.server.project.main.service.db.dao.user.UserWalletDao;
import app.server.project.main.service.service.upay.tron.constants.TxStatus;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.tron.trident.core.ApiWrapper;
import org.tron.trident.core.exceptions.IllegalException;
import org.tron.trident.core.key.KeyPair;
import org.tron.trident.proto.Chain;
import org.tron.trident.proto.Response;

import java.time.Instant;

import static app.server.project.main.service.service.upay.UPayType.Tron;
import static app.server.project.main.service.service.upay.tron.constants.TronConstants.Global_Tron_Active_URL;
import static app.server.project.main.service.service.upay.tron.constants.TronConstants.Tron_Active_URL;

@RequiredArgsConstructor
@Service
@Slf4j
public class TronAccountService {

    private final static int Try_Time = 5 * 60;

    private final UserWalletDao userWalletDao;
    private final CfgService cfgService;
    private final GlobalCfgDao globalCfgDao;
    private final TaskScheduler taskScheduler;
    private final EventService eventService;
    private final BlockService blockService;

    @EventListener(ApplicationReadyEvent.class)
    @Async(Def.CommonPool)
    public void init() {
        //批量检查激活钱包结果
        var userWalletEntityList = userWalletDao.getFailTx();
        for (var wallet : userWalletEntityList) {
            var data = userWalletDao.getWalletBy(wallet.getUserId(), Tron);
            //钱包已经激活
            if (data.isActive()) {
                continue;
            }
            //5分钟后查询
            this.taskScheduler.schedule(() -> {
                this.eventService.add(ChkActiveEvent.of(data));
            }, Instant.now().plusSeconds(Try_Time));
        }
    }

    /**
     * 获取tron用户钱包地址
     *
     * @param userId
     * @return
     */
    public String getTronAddress(long userId) {
        var data = userWalletDao.getWalletBy(userId, Tron);
        if (StrUtil.isBlank(data.getAddressHuman())) {
            KeyPair keyPair = KeyPair.generate();
            data.setAddressHuman(keyPair.toBase58CheckAddress());
            data.setAddressHex("0x" + keyPair.toHexAddress().substring(2));
            data.setPrivateKey(keyPair.toPrivateKey());
            data.setPublicKey(keyPair.toPublicKey());
            data.setBlockType(Tron);
            //更新钱包缓存
            userWalletDao.updateWallet(data);
            this.blockService.addAddress(data.getAddressHuman());
        }
        return data.getAddressHuman();
    }

    /**
     * 激活用户钱包
     */
    public String activeTronWallet(String address) throws IllegalException {
        String activeUrl = Tron_Active_URL;
        if (this.globalCfgDao.has(Global_Tron_Active_URL)) {
            activeUrl = this.globalCfgDao.getOneByKey(Global_Tron_Active_URL).getVal();
        }
        ApiWrapper client = this.cfgService.getActiveWalletClient();
        long amount = 1L; // Amount in SUN
        Response.TransactionExtention txn = client.transfer(activeUrl, address, amount);
        Chain.Transaction signedTxn = client.signTransaction(txn);
        return client.broadcastTransaction(signedTxn);
    }

    /**
     * 批量激活用户钱包
     */
    public void batchActiveTron() {
        var userWalletEntityList = userWalletDao.getBaseMapper().get10UUserUnActiveWalletList();
        for (var wallet : userWalletEntityList) {
            var data = userWalletDao.getWalletBy(wallet.getUserId(), Tron);
            //钱包已经激活
            if (data.isActive()) {
                continue;
            }
            //已经激活钱包
            if (data.isTx()) {
                continue;
            }
            this.eventService.add(ActiveEvent.of(data));
        }
    }

    @EventListener(ActiveEvent.class)
    public void activeOneWallet(ActiveEvent event) throws IllegalException {
        var data = event.getWallet();
        String txId = this.activeTronWallet(data.getAddressHuman());
        data.setActiveTxId(txId);
        data.setActiveTxFlag(TxStatus.Fail);
        //5分钟后查询
        this.taskScheduler.schedule(() -> {
            this.eventService.add(ChkActiveEvent.of(data));
        }, Instant.now().plusSeconds(Try_Time));
    }

    /**
     * 检查激活钱包结果
     *
     * @param
     */
    @EventListener(ChkActiveEvent.class)
    public void chkActiveTx(ChkActiveEvent event) throws IllegalException {
        var data = event.getWallet();
        var txData = this.cfgService.getBlockClient().getTransactionById(data.getActiveTxId());
        var contractResult = txData.getRet(0).getContractRet();
        if (contractResult == Chain.Transaction.Result.contractResult.SUCCESS) {
            //钱包激活成功
            data.setActive(Def.True);
            data.setActiveTxFlag(TxStatus.Success);
        }
    }


}
